package com.yaolong.api.modules.gen.utils;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author yaolong
 * @version V1.0.0
 * @program AgileFastFK3.0
 * @description
 * @create 2023-01-01 11:58
 **/
public class FileUtil {

    /**
     * <p>
     * 将字符写为文件
     * </p>
     *
     * @param filePath
     * @param fileContent
     * @return void
     * @version 1.0.0 <br>
     * @date 2023/1/1 10:33 <br>
     * @author yaolonga <br>
     */
    public static void writerStr2File(String filePath, String fileContent) {
        File file = new File(filePath);
        FileWriter fw;
        boolean exist = file.exists();
        BufferedWriter out = null;
        try {
            if (!exist) {
                File parentFile = file.getParentFile();
                com.baomidou.mybatisplus.generator.util.FileUtils.forceMkdir(parentFile);
            }
            fw = new FileWriter(file);
            out = new BufferedWriter(fw);
            out.write(fileContent, 0, fileContent.length() - 1);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }


    /**
     * <p>
     * 删除文件夹
     * </p>
     *
     * @param tempPath
     * @return void
     * @version 1.0.0 <br>
     * @date 2023/1/1 11:12 <br>
     * @author yaolonga <br>
     */
    public static void delFolder(String tempPath) throws IOException {
        boolean exists = new File(tempPath).exists();
        if (exists) {
            Path path = Paths.get(tempPath);
            Files.walkFileTree(path,
                    new SimpleFileVisitor<Path>() {
                        // 先去遍历删除文件
                        @Override
                        public FileVisitResult visitFile(Path file,
                                                         BasicFileAttributes attrs) throws IOException {
                            Files.delete(file);
                            System.out.printf("文件被删除 : %s%n", file);
                            return FileVisitResult.CONTINUE;
                        }

                        // 再去遍历删除目录
                        @Override
                        public FileVisitResult postVisitDirectory(Path dir,
                                                                  IOException exc) throws IOException {
                            Files.delete(dir);
                            System.out.printf("文件夹被删除: %s%n", dir);
                            return FileVisitResult.CONTINUE;
                        }
                    }
            );
        }

    }


    /**
     * <p>
     * packageZip
     * </p>
     *
     * @param filesPath  压缩的文件夹路径
     * @param outputPath 输出目录
     * @param zipName    压缩包名称
     * @return void
     * @version 1.0.0 <br>
     * @date 2023/1/1 12:09 <br>
     * @author yaolonga <br>
     */
    public static void packageZip(String filesPath, String outputPath, String zipName) throws Exception {
        // 要被压缩的文件夹
        File file = new File(filesPath);
        //放于和需要压缩的文件夹同级目录
        File zipFile = new File(outputPath + File.separator + zipName + ".zip");
        ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
        //判断是否为文件夹
        isDirectory(file, zipOut, "", true);
        zipOut.close();
    }

    public static void isDirectory(File file, ZipOutputStream zipOutputStream, String filePath, boolean flag) throws IOException {
        //判断是否为问加减
        if (file.isDirectory()) {
            //获取该文件夹下所有文件(包含文件夹)
            File[] files = file.listFiles();
            //首次为选中的文件夹，即根目录，之后递归实现拼接目录
            filePath = flag == true ? file.getName() : filePath + File.separator + file.getName();
            for (int i = 0; i < files.length; ++i) {
                //判断子文件是否为文件夹
                if (files[i].isDirectory()) {
                    //进入递归,flag置false 即当前文件夹下仍包含文件夹
                    isDirectory(files[i], zipOutputStream, filePath, false);
                } else {
                    //不为文件夹则进行压缩
                    InputStream input = new FileInputStream(files[i]);
                    zipOutputStream.putNextEntry(new ZipEntry(filePath + File.separator + files[i].getName()));
                    int temp = 0;
                    while ((temp = input.read()) != -1) {
                        zipOutputStream.write(temp);
                    }
                    input.close();
                }
            }
        } else {
            //将子文件夹下的文件进行压缩
            InputStream input = new FileInputStream(file);
            zipOutputStream.putNextEntry(new ZipEntry(file.getPath()));
            int temp = 0;
            while ((temp = input.read()) != -1) {
                zipOutputStream.write(temp);
            }
            input.close();
        }
    }


    /**
     * <p>
     * 文件下载
     * </p>
     *
     * @param filePath
     * @return void
     * @version 1.0.0 <br>
     * @date 2023/1/1 12:38 <br>
     * @author yaolonga <br>
     */
    public static void downloadFile(String filePath) {
        String name = new File(filePath).getName();
        try {
            HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            response.setCharacterEncoding("utf-8");
            response.setContentType("multipart/form-data");
            response.setHeader("Content-Disposition",
                    "attachment;fileName=" + setFileDownloadHeader(request, name));
            writeBytes(filePath, response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 输出指定文件的byte数组
     *
     * @param filePath 文件路径
     * @param os 输出流
     * @return
     */
    public static void writeBytes(String filePath, OutputStream os) throws IOException
    {
        FileInputStream fis = null;
        try
        {
            File file = new File(filePath);
            if (!file.exists())
            {
                throw new FileNotFoundException(filePath);
            }
            fis = new FileInputStream(file);
            byte[] b = new byte[1024];
            int length;
            while ((length = fis.read(b)) > 0)
            {
                os.write(b, 0, length);
            }
        }
        catch (IOException e)
        {
            throw e;
        }
        finally
        {
            if (os != null)
            {
                try
                {
                    os.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
            if (fis != null)
            {
                try
                {
                    fis.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
        }
    }


    /**
     * 下载文件名重新编码
     *
     * @param request 请求对象
     * @param fileName 文件名
     * @return 编码后的文件名
     */
    public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
    {
        final String agent = request.getHeader("USER-AGENT");
        String filename = fileName;
        if (agent.contains("MSIE"))
        {
            // IE浏览器
            filename = URLEncoder.encode(filename, "utf-8");
            filename = filename.replace("+", " ");
        }
        else if (agent.contains("Firefox"))
        {
            // 火狐浏览器
            filename = new String(fileName.getBytes(), "ISO8859-1");
        }
        else if (agent.contains("Chrome"))
        {
            // google浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        }
        else
        {
            // 其它浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        }
        return filename;
    }

}
